#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "can_rw.h"
#include "thread_ctrl.h"

#define CAN_MODE_START                      1

#define IOCTL_CAN_MAGIC                     'P'
#define IOCTL_CAN_SET_BITTIMING             _IOW(IOCTL_CAN_MAGIC, 16, struct can_bittiming)
#define IOCTL_CAN_SET_DATA_BITTIMING        _IOW(IOCTL_CAN_MAGIC, 18, struct can_bittiming)
#define IOCTL_CAN_SET_MODE                  _IOW(IOCTL_CAN_MAGIC, 21, int)

/* 打开 CAN 设备 */
int open_can(void *parent, const char *name, struct can_dev_t *pdev, uint8_t index)
{
    int *fd = &pdev->fd;
    char *path = pdev->path;

    /* 检查参数是否有效 */
    if (!parent || !name || !pdev) {
        fprintf(stderr, "Invalid parameters for %s, %p, %p, %p\n", 
                __func__, parent, name, pdev);
        return -EINVAL;
    }

    /* 生成设备路径 */
    pdev->parent = parent;
    pdev->index = index;
    int ret = snprintf(path, PATH_MAX, "/dev/%s%d", name, index);
    if (ret >= PATH_MAX || ret < 0) {
        fprintf(stderr, "Path too long or error in %s\n", __func__);
        return -ENAMETOOLONG;
    }

    /* 打开设备 */
    *fd = open(path, O_RDWR);
    if (*fd < 0) {
        int err = errno;
        fprintf(stderr, "Open %s device failed, %s\n", path, strerror(err));
        return -err;
    }
    printf("Open %s device success\n", path);

    return 0;
}

int set_can_baud_rate(int fd, struct can_bittiming *arbitration_baud, struct can_bittiming *data_baud)
{
    int ret = 0;

    ret = ioctl(fd, IOCTL_CAN_SET_BITTIMING, arbitration_baud);
    if (ret < 0) {
        fprintf(stderr, "Set arbitration baudrate failed\n");
        close(fd);
        return ret;
    }

    ret = ioctl(fd, IOCTL_CAN_SET_DATA_BITTIMING, data_baud);
    if (ret < 0) {
        fprintf(stderr, "Set data baudrate failed\n");
        close(fd);
        return ret;
    }

    return ret;
}

int start_can(int fd)
{
    int ret = 0;
    int mode = CAN_MODE_START;

    ret = ioctl(fd, IOCTL_CAN_SET_MODE, &mode);
    if (ret < 0) {
        fprintf(stderr, "Set start mode failed\n");
        close(fd);
        return ret;
    }

    return ret;
}

void *send_can_thread(void *arg) {
    struct can_dev_t *can_dev = (struct can_dev_t *)arg;
    struct can_param_t *pparam = can_dev->parent;
    struct thread_param_t *pthread = can_dev->write_thread;
    int infinite = (pparam->write_cnt == -1);
    int i = 0;
    int j = 0;
    int k = 0;
    int m = 0;
    char input[64];

    /* 检查参数是否有效 */
    if (!pthread || !pthread->name) {
        fprintf(stderr, "Invalid parameters for %s\n", __func__);
        return NULL;
    }

    /* 线程取消 SIGUSR1 的阻塞 */
    init_thread_user_signal();
    printf("Start %s send thread...\n", can_dev->path);
    while (!pthread->exit_sig) {
        for (i = 0; i < can_dev->baud_rate_cnt; i++) {
            printf("波特率 %d/%d [%dKbps/%dKbps]: 按回车开始发送 (q退出)...\n", 
                   i + 1, can_dev->baud_rate_cnt, can_dev->arbitration_baud[i].bitrate / 1000, 
                   can_dev->data_baud_rate[i].bitrate / 1000);
            fflush(stdout);
            while (!pthread->exit_sig) {
                if (fgets(input, sizeof(input), stdin) != NULL) {
                    if (input[0] == '\n')
                        break;
                    if (input[0] == 'q' || input[0] == 'Q') {
                        pthread->exit_sig = 1;
                        break;
                    }
                }
            }
            if (pthread->exit_sig) break;
            
            if (set_can_baud_rate(can_dev->fd, &can_dev->arbitration_baud[i], &can_dev->data_baud_rate[i]) < 0) {
                fprintf(stderr, "Set %s baud rate failed\n", can_dev->path);
            }
            if (start_can(can_dev->fd) < 0) {
                fprintf(stderr, "Start %s failed\n", can_dev->path);
            }
            printf("Start %s write...\n", can_dev->path);
            
            for (j = 0; j < can_dev->msg_type_cnt && !pthread->exit_sig; j++) {
                if (pparam->en_pause) {
                    printf("ID=0x%lx: 按回车开始发送 (q退出)...\n", can_dev->msg[j].id);
                    fflush(stdout);
                    while (!pthread->exit_sig) {
                        if (fgets(input, sizeof(input), stdin) != NULL) {
                            if (input[0] == '\n')
                                break;
                            if (input[0] == 'q' || input[0] == 'Q') {
                                pthread->exit_sig = 1;
                                break;
                            }
                        }
                    }
                    if (pthread->exit_sig) break;
                }
                for (k = 0; (pparam->write_cnt == -1 || k < pparam->write_cnt) && !pthread->exit_sig; k++) {
                    struct can_msg_t *msg = &can_dev->msg[j];
                    if (write(can_dev->fd, msg, 1) != 1) {
                        fprintf(stderr, "Write %s failed\n", can_dev->path);
                    } else {
                        printf("Send msg.id=0x%lx success\n", msg->id);
                    }

                    if (pparam->delay_ms > 0) {
                        for (m = 0; m < pparam->delay_ms && !pthread->exit_sig; m++) {
                            usleep(1000);
                        }
                    }
                }
            }
        }

        if (!infinite || pthread->exit_sig) {
            printf("infinite=%d, break\n", infinite);
            break;
        } else {
            usleep(1000000);
        }
    }

    // close(can_dev->fd);
    printf("%s %s return\n", can_dev->path, __func__);

    return NULL;
}

void *recv_can_thread(void *arg) {
    struct can_dev_t *can_dev = (struct can_dev_t *)arg;
    struct can_param_t *pparam = (struct can_param_t *)can_dev->parent;
    struct thread_param_t *pthread = can_dev->read_thread;
    struct can_msg_t msg;
    int i = 0;
    int j = 0;
    int nbytes = 0;

    /* 检查参数是否有效 */
    if (!pthread || !pthread->name) {
        fprintf(stderr, "Invalid parameters for %s\n", __func__);
        return NULL;
    }

    /* 线程取消 SIGUSR1 的阻塞 */
    init_thread_user_signal();
    printf("Start %s receive thread...\n", can_dev->path);
    while (!pthread->exit_sig) {
        for (i = 0; (pparam->read_cnt == -1 || i < pparam->read_cnt) && !pthread->exit_sig; i++) {
            nbytes = read(can_dev->fd, &msg, 1);
            if (nbytes < 0) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    printf("No data available %s, waiting...\n", can_dev->path);
                    usleep(10000);
                    continue;
                }
                fprintf(stderr, "Read %s failed with errno %d\n", can_dev->path, nbytes);
                break;
            } else if (nbytes == 1) {
                printf("Received CAN FD message:\n");
                printf("  Format: %s\n", msg.fmt ? "Extended" : "Standard");
                printf("  RTR: %s\n", msg.rtr ? "Remote Frame" : "Data Frame");
                printf("  ID: 0x%lX\n", msg.id);
                printf("  DLC: %u\n", msg.dlc);
                printf("  CAN Flag: %s\n\n", msg.flg ? "CAN FD" : "CAN");
                // printf("  Data Length: %u bytes\n", msg.dlc <= 8 ? msg.dlc : 8 + (msg.dlc - 8) * 4);

                printf("  Data: ");
                for (j = 0; j < msg.dlc; j++) {
                    printf("%02X ", msg.data[j]);
                }
                printf("\n");
            } else {
                printf("Read %s %d frames, expected %u)\n", can_dev->path, nbytes, 1);
                break;
            }
        }
        printf("Read %s %d frames done\n", can_dev->path, pparam->read_cnt);
        break;
    }
    close(can_dev->fd);
    printf("%s %s return\n", can_dev->path, __func__);

    return NULL;
}
